class Student
{
public:
  Student():name(""), gender(""), age(0){};
  Student(String iname, String igender, uint8_t iage):name(iname), gender(igender), age(iage){};
  String name;
  String gender;
  uint8_t age;
};

Student allStudents[10] = {Student("Tom","man",16),
Student("Jack","man",18),
Student("Alice","women",17),
Student("Ming","man",16),
Student("Lili","women",16),
Student("Alan","man",16),
Student("Bluce","man",15),
Student("Ben","man",17),
Student("Mei","women",18),
Student("Ben","man",16)
};

#define MaxQueueSize 32
QueueHandle_t QueueHandle = nullptr;

void producerTask(void* p)
{
  static uint8_t index = 0;
  TickType_t tickCount = xTaskGetTickCount();
  while(1)
  {
    if(uxQueueSpacesAvailable(QueueHandle) > 0)
    {
      if(pdTRUE != xQueueSend(QueueHandle, (void*) &allStudents[index++], 0))
      {
        Serial.println("xQueueSend failed.");
      }
    }
    else
    {
      Serial.println("Queue is full.");
    }
    if(index > 9)
    {
      index = 0;
    }
    vTaskDelayUntil(&tickCount, 1000);
  }
}

void consumerTask(void* p)
{
  const uint32_t waitTime = 500;//tick
  Student student;
  TickType_t tickCount = xTaskGetTickCount();
  while(1)
  {
    if(pdPASS == xQueueReceive(QueueHandle, &student, waitTime))
    {
      Serial.print("The student is ");
      Serial.print(student.name);
      Serial.print(", age ");
      Serial.println(student.age);
    }
    else
    {
      Serial.println("Time out, no data in queue.");
    }
  }
}

void setup()
{
  Serial.begin(115200);
  QueueHandle = xQueueCreate(MaxQueueSize, sizeof(Student));
  if(QueueHandle == nullptr)
  {
    Serial.println("Err: xQueueCreate filed, reboot system.");
    ESP.restart();
  }
  xTaskCreate(producerTask, "producer", 2048, nullptr, 1, nullptr);
  xTaskCreate(consumerTask, "consumer", 2048, nullptr, 1, nullptr);
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}
